package com.rcn.sne;

import java.util.List;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.hibernate.HibernateException;

import com.rcn.core.Patient;
import com.rcn.core.exception.RaccoonException;
import com.rcn.dal.interfaces.IPatientDAO;
import com.rcn.db.DBManager;

public class SneManager 
{
	private static Logger log = LogManager.getLogger(SneManager.class.getName());
	private IPatientDAO patientDao = DBManager.getManagerDAO().getPatientDAO();
	
	@SuppressWarnings("unchecked")
	public List<Patient> getAllPatients() throws RaccoonException
	{
		log.debug("Getting all patients...");
		return getPatientDao().getAll(Patient.class);
	}

	/**
	 * Delete a patient
	 * @param id Id of the patient who will be deleted
	 * @throws RaccoonException
	 */
	public void deletePatient(long id) throws RaccoonException
	{
		log.debug("Deleting patient");
		try{
			int rows = getPatientDao().deleteById(id);
			if(rows == 0){
				throw new RaccoonException(RaccoonException.ERROR_MESSAGE.PATIENT_NOT_FOUND.toString(), null);
			}
		} 
		catch (HibernateException e){
			log.error("Error ocurred trying to delete the patient.",e);
			throw new RaccoonException(RaccoonException.ERROR_MESSAGE.UNKNOWN.toString(), e);
		}
	}
	
	/**
	 * Get a patient
	 * @param id
	 * @return
	 * @throws RaccoonException
	 */
	public Patient getPatient(long id) throws RaccoonException
	{
		log.debug("Getting patient Id: "+id);
		Patient p;
		try{
			p = (Patient) getPatientDao().getById(Patient.class, String.valueOf(id));
			if(p == null){
				throw new RaccoonException(RaccoonException.ERROR_MESSAGE.PATIENT_NOT_FOUND.toString(), null);
			}
		}
		catch(HibernateException e){
			log.error("Error trying to get patient with id: "+id);
			throw new RaccoonException(RaccoonException.ERROR_MESSAGE.UNKNOWN.toString(), e);
		}
		return p;
	}
	
	public long savePatient(Patient p) throws RaccoonException
	{
		log.debug("Saving patient. "+ p.getName()+" "+p.getSurname());
		long generatedId = -1;
		try {
			//first check if the patient already exists (using idNumber)
			if(isPatientSaved(p)){
				log.debug("Patient already exists.");
				throw new RaccoonException(RaccoonException.ERROR_MESSAGE.DUPLICATE_PATIENT.toString(), null);
			}
			//if not save it
			generatedId = getPatientDao().save(p);
			log.debug("Patient saved. Id: "+generatedId);
		}
		catch (HibernateException e) {
			log.error("Error trying to save patient: "+p.getName()+" "+p.getSurname());
			throw new RaccoonException(RaccoonException.ERROR_MESSAGE.ERROR_SAVE_PATIENT.toString(), e);
		}catch (ClassCastException e){
			throw new RaccoonException(RaccoonException.ERROR_MESSAGE.UNKNOWN.toString(), e);
		}
		return generatedId;
	}
	
	/**
	 * Checks if the patient already exists in the database using the idNumber (NOT ID but IDNUMBER :))
	 * true = when exists, false otherwise
	 * @param p
	 * @return
	 */
	private boolean isPatientSaved(Patient p) {
		log.debug("Verifying if patient with id: "+p.getIdNumber()+ " already exists.");
		boolean saved = false;
		Patient storedPatient = getPatientDao().getByIdNumber(p.getIdNumber());
		if(storedPatient != null){
			saved = true;
		}
		return saved;
	}
	
	public void updatePatient(Patient p) throws RaccoonException
	{
		log.debug("Updating patient. "+ p.getName()+" "+p.getSurname());
		try {
			
			Patient old = this.getPatient(p.getId());
			
			old.setAddress(p.getAddress());
			old.setBirthDate(p.getBirthDate());
			old.setIdNumber(p.getIdNumber());
			old.setName(p.getName());
			old.setSurname(p.getSurname());
			old.setTelephone(p.getTelephone());
			old.setNotes(p.getNotes());
			getPatientDao().update(old);
			log.debug("Patient updated. Id: "+old.getId());
		}
		catch (RaccoonException e) {
			log.error("Error trying to update patient: "+p.getName()+" "+p.getSurname());
			throw e;
		}
	}

	public IPatientDAO getPatientDao() {
		return patientDao;
	}

	public void setPatientDao(IPatientDAO patientDao) {
		this.patientDao = patientDao;
	}
}
